package jmine.tec.services.io;

import java.util.HashMap;
import java.util.Map;

import jmine.tec.services.api.ActionsEnum;
import bancosys.tec.persist.base.enumx.EnumUtils;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * Bean que representa um serviço da planilha.
 * 
 * @author Kendji
 */
@XStreamAlias("service")
@XStreamConverter(ServiceBeanXStreamConverter.class)
public class ServiceBean implements Comparable<ServiceBean> {

    private String name;

    private ActionsEnum action;

    private int row;

    private String serviceLocation;

    private Map<String, Object> parameters;

    private String comment;

    private static final transient XStream XSTREAM;

    static {
        XSTREAM = new XStream(new DomDriver());
        XSTREAM.alias("service", ServiceBean.class);
        XSTREAM.autodetectAnnotations(true);
    }

    /**
     * @return the name
     */
    public String getName() {
        return this.name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the action
     */
    public ActionsEnum getAction() {
        return this.action;
    }

    /**
     * @param action the action to set
     */
    public void setAction(ActionsEnum action) {
        this.action = action;
    }

    /**
     * Define o valor da action a partir de uma string.
     * 
     * @param ac action
     */
    public void setActionAsString(String ac) {
        this.setAction(EnumUtils.getEnumByValue(ActionsEnum.class, ac));
    }

    /**
     * @return the row
     */
    public int getRow() {
        return this.row;
    }

    /**
     * @param row the row to set
     */
    public void setRow(int row) {
        this.row = row;
    }

    /**
     * @return the serviceLocation
     */
    public String getServiceLocation() {
        return this.serviceLocation;
    }

    /**
     * @param serviceLocation the serviceLocation to set
     */
    public void setServiceLocation(String serviceLocation) {
        this.serviceLocation = serviceLocation;
    }

    /**
     * @return the comment
     */
    public String getComment() {
        return this.comment;
    }

    /**
     * @param comment the comment to set
     */
    public void setComment(String comment) {
        this.comment = comment;
    }

    /**
     * @return the parameters
     */
    public Map<String, Object> getParameters() {
        if (this.parameters == null) {
            // XXX Rafael: Not "UpperCase" safe.
            this.parameters = new HashMap<String, Object>();
        }

        return this.parameters;
    }

    /**
     * @param parameters the parameters to set
     */
    public void setParameters(Map<String, Object> parameters) {
        this.parameters = parameters;
    }

    /**
     * Inclui um parâmetro no mapa.
     * 
     * @param key chave
     * @param value valor
     */
    public void putParameter(String key, String value) {
        this.getParameters().put(key, value);
    }

    /**
     * Cria ServiceBean a partir do xml passado.
     * 
     * @param xml xml com dados de serviceBean.
     * @return serviceBean a partir do xml passado.
     */
    public static ServiceBean fromXml(String xml) {
        return (ServiceBean) XSTREAM.fromXML(xml);
    }

    /**
     * @return xml representado esse bean.
     */
    public String toXml() {
        return XSTREAM.toXML(this);
    }

    /**
     * @return xml representando esse bean.
     */
    @Override
    public String toString() {
        return this.toXml();
    }

    /**
     * Retorna uma String no formato Action.ServiceName.
     * 
     * @return uma String no formato Action.ServiceName
     */
    public String getServiceFullName() {
        String actionString = this.getAction() == null ? "UNKNOWN" : this.getAction().toString();
        return actionString + this.getName();
    }

    /**
     * Compara esse ServiceBean com o serviceBean passado como parametro.
     * 
     * @param other outra instancia de um ServiceBean
     * @return -1, 0 ou 1
     */
    public int compareTo(ServiceBean other) {
        String serviceName = this.getAction().toString() + this.getName();
        String otherServiceName = other.getAction().toString() + other.getName();
        return serviceName.compareTo(otherServiceName);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((this.action == null) ? 0 : this.action.hashCode());
        result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
        result = prime * result + ((this.parameters == null) ? 0 : this.parameters.hashCode());
        return result;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (this.getClass() != obj.getClass()) {
            return false;
        }
        ServiceBean other = (ServiceBean) obj;
        if (this.action != other.action) {
            return false;
        }
        if (this.name == null) {
            if (other.name != null) {
                return false;
            }
        } else if (!this.name.equals(other.name)) {
            return false;
        }
        if (this.parameters == null) {
            if (other.parameters != null) {
                return false;
            }
        } else if (!this.parameters.equals(other.parameters)) {
            return false;
        }
        return true;
    }
}
